package com.jiefeng.manager.service.springsecurity;

import com.jiefeng.dao.security.WebResourceAuthorityMapper;
import com.jiefeng.manager.table.springsecurity.WebResourceAuthority;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class MyInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

    private final static Logger logger = LoggerFactory.getLogger(ExpressionBasedFilterInvocationSecurityMetadataSource.class);

    private static Map<String, Collection<ConfigAttribute>> resourceMap = new HashMap<String, Collection<ConfigAttribute>>();;

    @Autowired
    WebResourceAuthorityMapper webResourceAuthorityMapper;

    public MyInvocationSecurityMetadataSource(){}

    //在构造函数中直接添加 加载配置权限的函数,会因spring实例化bean时的加载顺序问题，而出现空指针异常
    public void init() {
        loadResourceDefine();
    }
    
    public MyInvocationSecurityMetadataSource(Map<String, Collection<ConfigAttribute>> resourceMap)
    {
        this.resourceMap = resourceMap;
    }

    //在这个方法中添加获取securityContext.xml中访问资源配置的权限
    private void loadResourceDefine() {

        // 以下为从数据库中取得资源权限信息
        List<WebResourceAuthority> webResourceAuthoritys = webResourceAuthorityMapper.query(new WebResourceAuthority());
        for(WebResourceAuthority webResourceAuthority : webResourceAuthoritys)
        {
            Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
            String urlResource = webResourceAuthority.getUrlResource();
            String urlAuthority = webResourceAuthority.getUrlAuthority();
            String[]  authorities = urlAuthority.toUpperCase().split(",");
            for(int j=0; j<authorities.length; j++)
            {
                ConfigAttribute configAttribute=new SecurityConfig(authorities[j]);
                atts.add(configAttribute);
            }
            resourceMap.put(urlResource, atts);
        }
    }

    // According to a URL, Find out permission configuration of this URL.
    /**
     * 这个类中，还有一个最核心的地方，就是提供某个资源对应的权限定义，即getAttributes方法返回的结果。
     * 注意，我例子中使用的是AntUrlPathMatcher这个path matcher来检查URL是否与资源定义匹配，
     * 事实上你还要用正则的方式来匹配，或者自己实现一个matcher。
     *
     */
    public Collection<ConfigAttribute> getAttributes(Object object)
            throws IllegalArgumentException {
        // guess object is a URL.
        String url = ((FilterInvocation)object).getRequestUrl();
        Iterator<String> ite = resourceMap.keySet().iterator(); //在请求url和配置的url之间进行比对，看是否请求的url在
        //配置的url里面
        while (ite.hasNext())
        {
            String resourceURL = ite.next();
            AntPathRequestMatcher matcher=new AntPathRequestMatcher(resourceURL,null);
            if (matcher.matches(((FilterInvocation)object).getHttpRequest())) {     //在这里只进行了简单的比对，以后设计比对方法
                return resourceMap.get(resourceURL);  //请求URL进行了权限配置则返回，他的所有权限信息
            }
        }
        return null;
    }

    public boolean supports(Class<?> clazz) {
        return true;
    }
    
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    public static Map<String, Collection<ConfigAttribute>> getResourceMap() {
        return resourceMap;
    }

    public static void setResourceMap(Map<String, Collection<ConfigAttribute>> resourceMap) {
        MyInvocationSecurityMetadataSource.resourceMap = resourceMap;
    }

}
